package com.ctfo.ulcp.exp.core

import com.ctfo.ulcp.exp.db.*
import kotlinx.coroutines.future.await
import org.slf4j.LoggerFactory


class CoreService(private val projectCode: String, private val model: LLMModel) {
    private lateinit var project: Project
    private lateinit var resources: List<Resource>

    private val logger = LoggerFactory.getLogger(CoreService::class.java)
    private lateinit var userInput: String
    private var resourceManager: ResourceManager? = null


    init {
        DSL.transaction {
            project = requireNotNull(Projects.findByCode(projectCode)) { "project not found for $projectCode" }
            resources = Resources.findByProjectId(project.id!!)
            logger.info("project:{}, resources:{}", project, resources)
        }

    }


    suspend fun answer(input: String): String {
        this.userInput = input
        val route = callRoute()
        return when (route) {
            RouteType.Direct -> PyCaller.callQuestion(model, userInput).await().output
            RouteType.Code -> callCode()
            RouteType.Doc -> callDoc()
        }

    }

    private suspend fun callDoc(): String {
        val resourceManager = getResourceManager()
        val docInfo = resourceManager.searchDocEmbedding(userInput, 10)
        return PyCaller.callDoc(model, userInput, docInfo).await().output
    }

    private suspend fun callCode(): String {
        val resourceManager = getResourceManager()
        val dbInfo = ""
        val apiInfo = ""
        return PyCaller.callCode(model, userInput, dbInfo, apiInfo).await().output
    }

    @Synchronized
    private fun getResourceManager(): ResourceManager {
        if (resourceManager == null) {
            resourceManager = ResourceManagerFactory.resourceManagerForProject(project.id!!)
        }
        return resourceManager!!
    }


    private suspend fun callRoute(): RouteType {
        val businessSummary = project.summary
        val docSummary = resources.filter { it.type == ResourceType.DOC }.joinToString("\n") { it.summary }
        val dataSummary = resources.filter { it.type == ResourceType.DB }.joinToString("\n") { it.summary }
        val interfaceSummary = resources.filter { it.type == ResourceType.API }.joinToString("\n") { it.summary }

        try {
            val routeCode =
                PyCaller.callRoute(model, userInput, businessSummary, docSummary, dataSummary, interfaceSummary).await()
            return RouteType.fromCode(routeCode)
        } catch (e: Exception) {
            logger.error("route err:", e)
            return RouteType.Direct
        }

    }


}

suspend fun main() {
    val service = CoreService("ctfo-platform", LLMModel.OpenAI)
    val answer = service.answer("请介绍一下酒后驾驶的危害")
    println("answer: \n$answer")
}